/*
*
* METROVIEW
*
*/

// import libraries
import processing.pdf.*;
import controlP5.*;
import org.gicentre.utils.move.*;
import org.gicentre.utils.colour.*;

// define variables
// NOTE: really need to figure out if I should just be declaring here,
// or declaring and assigning, or whatever, and organize this a bit
ZoomPan zoomer;
ControlP5 controlP5;
ColourManager colourMan = new ColourManager();
PDFUI pdfui;
StaticUI sui;
ScaleUI scal;
ModeSelectorUI msui;
NHoodInfoUI nhui;
PDFMaker pdfm = new PDFMaker();
NHood[] hoods;
float[][] maxMins;
float latMin = 0.35;      // min latitude is 53.2 but numerals before decimal point removed to maintain precision
float latMax = 0.75;      // max latitude is 53.8 but numerals before decimal point removed to maintain precision
float longMin = -0.75;    // min longitude is -113.8 but numerals before decimal point removed to maintain precision
float longMax = -0.25;    // max longitude is -113.2 but numerals before decimal point removed to maintain precision
String[] dModeNames = {   "Neighbourhoods" ,            // array of names of drawing modes
                          "Average age" ,
                          "% renters" ,
                          "% owners" ,
                          "People per dwelling" ,
                          "Average income" ,
                          "Median income" ,
                          "Number residential structures" ,
                          "% Single detached" ,
                          "% Duplex/rowhouse" ,
                          "% Apartments >= 5 stories" ,
                          "% Apartments < 5 stories" ,
                          "% Occupied" ,
                          "% Unoccupied" ,
                          "% Under construction" ,
                          "% No longer in use" ,
                          "% Vacant lots" ,
                      };
int dMode = 0;            // integer representing "drawing mode;" set to 0 (default value)
int[] dFil = { 200, 200, 200 };        // "default" fill
int[] noDataFil = { 128, 128, 128};    // "no data" fill -- used to fill neighbourhoods when the neighbourhood has no data
int[] strok = { 75, 75, 75, 100 };     // "default" stroke


void setup() {
  
  // CREATE WINDOW
  
  size(700, 700);
  background(240);
  cropLatLong();
  
  // READ DATA
  
  // build neighbourhoods
  KMLReader kmlr = new KMLReader(this);
  
  // read neighbourhood kml and csv files
  String[][] kmlData = kmlr.readKML();
  String[][] censusData = kmlr.readNInfo();
  String[][] otherData = kmlr.readNOtherInfo();
  
  // create neighbourhood objects and calculate metrics
  NMaker nm = new NMaker(kmlData, censusData, otherData);
  hoods = nm.makeNHoods();
  maxMins = nm.calcNHoodMaxMin(hoods);   // calculate metric max and mins
 
  // SET VARIABLES
  
  controlP5 = new ControlP5(this);                                            // "parent" UI object
  zoomer = new ZoomPan(this);                                                 // object for zooming and panning
  sui = new StaticUI(controlP5, this);                                        // object encapsulating static UI components
  scal = new ScaleUI(controlP5, this, maxMins, dModeNames, 10, 44, 20, 60);               // scale for interpreting plot values
  msui = new ModeSelectorUI(controlP5, this, dModeNames, 6, 187, 225, 300);  // list box for selecting the drawing mode
  nhui = new NHoodInfoUI(controlP5, 6, 124, 225, 43);                        // "neighbourhood info" box that displays neighbourhood info based on mouse position
  pdfui = new PDFUI(controlP5, this, 79, 78, 75, 15);                      // create pdf button
   
  // COMPLETE OPERATIONS
    
  zoomer.setZoomMouseButton(PConstants.RIGHT);          // set mouse button for zooming/panning
  
  // SET GRAPHIC PARAMETERS
  
  smooth();
  strokeWeight(0.4);
  
  // 
}

void draw() {
 
  // CHECK PDF RECORDING
  pdfm.recordOn();
  
  // SET UP ZOOMING/PANNING
  
  // draw background
  background(245); 
  
  // store a copy of unzoomed screen transformation
  pushMatrix();
  
  // Enable the zooming/panning.
  zoomer.transform();
  
  // for some reason transforms applied by ZoomPan object
  // don't register with the pdf writing library. Therefore, if
  // writing pdf, apply these manually
  if(pdfm.checkRecord()) {

    pushMatrix();
    
    // extract ZoomPan transform vector and scale
    PVector orig = new PVector(0, 0); 
    PVector transform = zoomer.getCoordToDisp(orig);
    float s = (float) zoomer.getZoomScale();
    // re-apply transforms
    scale(s);
    translate(transform.x/s, transform.y/s);
  } // if
  
  
  // DRAW DYNAMIC OBJECTS
  
  // get mouse coordinates, accounting for zoom and pan
  PVector vPoin = zoomer.getMouseCoord();
  float[] poin = { vPoin.x, vPoin.y };
  
  // hide objects updated when mouse is over neighbourhoods, so
  // they don't display if the mouse isn't over any neighbourhoods
  nhui.hideDynamic();
  
  // draw neighbourhoods and check if mouse is over each neighbourhood
  for(int i = 0; i < hoods.length; i++) {
    hoods[i].draw(dMode, maxMins, colourMan);
    hoods[i].checkMouseOver(poin, nhui, dMode);
  }
  
  if(pdfm.checkRecord()) {
    
    popMatrix();
    sui.draw(true);
    scal.draw(dMode, colourMan, true);
    
    // CHECK PDF RECORDING
    pdfm.recordOff();
  }
  
  // DRAW STATIC OBJECTS
  
  // Restore the unzoomed screen transformation.
  popMatrix();    
  
  // draw static UI components
  sui.draw(false);
  scal.draw(dMode, colourMan,false);
  msui.draw();
  nhui.drawStatic();
  pdfui.draw();
  
}

// CONTROLP5 EVENT LISTENER

// ------------------------------------
// controlEvent
// this is a "standard" controlP5 method that
// is used to listen for events
// -------------------------------------
void controlEvent(ControlEvent event) {
  
  // check type of event
  if(event.isGroup()) {
    // this is for events coming from the ModeSelectorUI
    if(event.group().id() == 1) {
      dMode = (int) event.group().value();
    } // if
  } else if(event.isController()) {
    if(event.controller().id() == 2) {
      String path = selectOutput();
      if(path != null) {
        pdfm.switchRecord();
        pdfm.path = path;
      }
    } // if
  } // if
  
} // controlP5 event listener
